<script lang="ts" setup>
/**
 * @property {Boolean}						disabled		是否禁用（默认 false ）
 * @property {String | Number}				size			开关尺寸，单位px （默认 20 ）
 * @property {String}						activeColor		打开时的背景色 （默认 '#2979ff' ）
 * @property {String} 						inactiveColor	关闭时的背景色 （默认 '#ffffff' ）
 * @property {Boolean | String | Number}	activeValue		打开选择器时通过change事件发出的值 （默认 true ）
 * @property {Boolean | String | Number}	inactiveValue	关闭选择器时通过change事件发出的值 （默认 false
 */
const emit = defineEmits(['change', "update:modelValue", 'beforeChange']);
const props = defineProps({
  modelValue: {
    type: [Boolean, String, Number],
    default: false
  },
  disabled: {
    type: Boolean,
    default: false
  },
  activeColor: {
    type: String,
    default: '#25CF42'
  },
  inactiveColor: {
    type: String,
    default: '#BBBBBB'
  },
  activeValue: {
    type: [String, Number, Boolean],
    default: true
  },
  inactiveValue: {
    type: [String, Number, Boolean],
    default: false
  },
  size: {
    type: Number,
    default: 20
  },
  asyncAction: {
    type: Boolean,
    default: false
  },
  loading: {
    type: Boolean,
    default: false
  }
});

const innerValue: any = ref(props.modelValue);

onMounted(() => {
  innerValue.value = props.modelValue;
})

watch(() => props.modelValue, (val) => {
  innerValue.value = val;
})

const isActive: any = computed(() => {
  return innerValue.value === props.activeValue;
})
const switchStyle = computed(() => {
  return {
    width: Number(props.size) * 2 + 4 + 'px',
    height: Number(props.size) + 4 + 'px',
    backgroundColor: isActive.value ? props.activeColor : props.inactiveColor,
    borderRadius: '24px'
  }
})
const nodeStyle = computed(() => {
  return {
    width: props.size + 'px',
    height: props.size + 'px',
    transform: `translate(${ isActive.value ? props.size + 'px' : 0 }, 0)`,
    padding: '1px',
    left: '2px',
    top: '2px'
  }
})
const bgStyle: any = computed(() => {
  return {
    width: Number(props.size) * 2 - Number(props.size) / 2 + 'px',
    height: Number(props.size) + 'px',
    backgroundColor: props.inactiveColor,
    transform: `scale(${isActive.value ? 0 : 1})`
  }
})
const iconStyle: any = computed(() => {
  return {
    width: props.size - 2 + 'px',
    height: props.size - 2 + 'px'
  }
})

function clickHandler() {
  if (!props.disabled) {
    if(props.asyncAction) {
      emit('beforeChange',{oldValue: innerValue.value, newValue: !innerValue.value});
      // innerValue.value = !innerValue.value;
    } else {
      const oldValue = isActive.value ? props.inactiveValue : props.activeValue;
      emit('change', oldValue);
      emit('update:modelValue', oldValue)
    }
  }
}
</script>

<template>
  <div class="vc-switch" :class="[disabled && 'vc-switch--disabled']" :style="switchStyle"
    @click="clickHandler">
    <div class="vc-switch-bg" :style="bgStyle"></div>
    <div class="vc-switch-node" :style="nodeStyle">
      <div class="switch-icon" :style="iconStyle" :class="[loading ? 'loading-icon' :innerValue && 'switch-icon-on']"></div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.vc-switch {
  padding: 0;
  margin: 0!important;
  display: block;
  box-shadow: none;
  box-sizing: border-box;
  position: relative;
  background-color: #fff;
  overflow: hidden!important;
  top: 0;
  left: 0;
  z-index: 3;

  .vc-switch-node {
    position: absolute;
    z-index: 9;
    border-radius: 100%;
    transition: transform 0.4s cubic-bezier(0.3, 1.05, 0.4, 1.05);
  }
  .switch-icon {
    display: block;
    background-image: url('@/assets/switch2x.png');
    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
  }
  .switch-icon-on {
    background-image: url('@/assets/switch2x.png');
  }
  .loading-icon{
    background-image: url('@/assets/s-loading-icon.png');
    animation: rotate 2s linear infinite;
  }

  .vc-switch-bg {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 9;
    border-radius: 100%;
    background-color: #FFFFFF;
    transition: transform 0.4s ease;
    background: blue;
  }

  &--disabled {
    opacity: 0.6;
  }
}
/* 定义旋转动画 */
@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
</style>
